package com.szosen.device.jianhuyi;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;

import android.R.bool;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

public class BeneCheckDeviceHB {
	public static final String TAG = "123456789";
	private UsbManager mUsbmanager;
	private PendingIntent mPendingIntent;
	private UsbDevice mUsbDevice;
	private UsbInterface mInterface;
	private UsbEndpoint mCtrlPoint;
	private UsbEndpoint mBulkInPoint;
	private UsbEndpoint mBulkOutPoint;
	public static final int WHAT_RECEIVE_TIMEOUT = 43;
	private UsbDeviceConnection mDeviceConnection;
	private Context mContext;
	private String APPName;// APP名称
	// 设备地址和设备数量
	private ArrayList<String> DeviceNum = new ArrayList<String>();
	private int DeviceCount;
	private int mBulkPacketSize;// 数据包大小
	private int DEFAULT_TIMEOUT = 500;
	public Handler handler;
	protected final Object WriteQueueLock = new Object();

	// public static final int MESSAGE_READ = 0x401185;// 读入数据信号
	public BeneCheckDeviceHB(UsbManager manager, Context context,
			String AppName, Handler myhandler) {
		super();
		mUsbmanager = manager;
		mContext = context;
		APPName = AppName;
		handler = myhandler;
		// ArrayAddDevice("1a86:7523");
		EnumerateDevice(mUsbmanager);
		USBEndPoint(mUsbDevice);
		OpenDevice(mUsbDevice);
	}

	// 设备地址
	private void ArrayAddDevice(String str) {
		DeviceNum.add(str);
		DeviceCount = DeviceNum.size();
	}

	// 枚举出设备
	@SuppressLint("NewApi")
	public void EnumerateDevice(UsbManager myUsbManager) {
		if (myUsbManager == null) {
			return;
		}
		System.out.println("枚举设备");
		HashMap<String, UsbDevice> deviceList = myUsbManager.getDeviceList();
		if (deviceList.isEmpty()) {
			handler.obtainMessage(44).sendToTarget();
			Toast.makeText(mContext, "没有找到可用usb设备！", Toast.LENGTH_SHORT).show();
			return;
		}
		Iterator<UsbDevice> localIterator = deviceList.values().iterator();
		while (localIterator.hasNext()) {
			UsbDevice localUsbDevice = localIterator.next();
			// for (int i = 0; i < DeviceCount; ++i) {
			int vendorID = localUsbDevice.getVendorId();
			int productID = localUsbDevice.getProductId();
			System.out.println("VendorId" + vendorID);
			System.out.println("productID" + productID);
			if ((vendorID == 1027 && productID == 24577)) {
				// 在获得设备的时候，同时注册一个广播。
				mUsbDevice = localUsbDevice;// 对象
				IntentFilter filter = new IntentFilter(APPName);
				filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
				mContext.registerReceiver(mUsbReceiver, filter);

			} else {
				Log.d(TAG, "String.format not match");
			}
			// }
		}
	}

	// 获取到USB接口
	@SuppressLint("NewApi")
	public UsbInterface USBEndPoint(UsbDevice mDevice) {
		UsbInterface usbinterface = null;
		if (mDevice != null) {
			usbinterface = getUsbInterface(mDevice);
			if (usbinterface == null) {
				System.out.println("空指针");
				return null;
			}
			for (int i = 0; i < usbinterface.getEndpointCount(); ++i) {
				UsbEndpoint endPoint = usbinterface.getEndpoint(i);
				if (endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
					if (endPoint.getDirection() == UsbConstants.USB_DIR_IN) {
						mBulkInPoint = endPoint;
					} else if (endPoint.getDirection() == UsbConstants.USB_DIR_OUT) {
						mBulkOutPoint = endPoint;
					}
					/*
					 * if (endPoint.getDirection() == UsbConstants.USB_DIR_OUT)
					 * { mBulkOutPoint = endPoint;
					 * 
					 * } else { mBulkInPoint = endPoint; }
					 */
					this.mBulkPacketSize = endPoint.getMaxPacketSize();
				} else if (endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_CONTROL) {
					mCtrlPoint = endPoint;
				}
			}
			return usbinterface;
		}
		return null;
	}

	@SuppressLint("NewApi")
	private UsbInterface getUsbInterface(UsbDevice paramUsbDevice) {
		if (this.mDeviceConnection != null) {
			if (this.mInterface != null) {
				this.mDeviceConnection.releaseInterface(this.mInterface);
				this.mInterface = null;
			}
			this.mDeviceConnection.close();
			this.mUsbDevice = null;
			this.mInterface = null;
		}
		if (paramUsbDevice == null)
			return null;
		for (int i = 0; i < paramUsbDevice.getInterfaceCount(); i++) {
			UsbInterface intf = paramUsbDevice.getInterface(i);
			return intf;

		}
		return null;
	}

	// 在打开设备前先判断是否有权限，打开设备；
	@SuppressLint("NewApi")
	public void OpenDevice(UsbDevice mDevice) {
		mPendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(
				APPName), 0);
		UsbDeviceConnection connUSBDevice = null;
		// 如果有权限，就打开APP
		if (mDevice != null && mUsbmanager != null) {
			UsbInterface GetUsbinterface = USBEndPoint(mDevice);
			if (mUsbmanager.hasPermission(mDevice)) {
				if (GetUsbinterface != null) {
					// 打开USB设备
					connUSBDevice = this.mUsbmanager.openDevice(mDevice);
					// System.out.println("设备已打开");
					if (connUSBDevice != null) {
						if (connUSBDevice.claimInterface(GetUsbinterface, true)) {
							this.mUsbDevice = mDevice;
							this.mDeviceConnection = connUSBDevice;
							this.mInterface = GetUsbinterface;
							// 设置属性
							if (SetConfig(38400, (byte) 1, (byte) 8, (byte) 0,
									(byte) 0) == true) {
								handler.obtainMessage(5, "设备打开成功！")
										.sendToTarget();
								readThread = new read_thread(mBulkInPoint,
										connUSBDevice);
								readThread.start();
							} else {
								handler.obtainMessage(4, "设备打开失败！")
										.sendToTarget();
							}
							return;
						}
					}
				}
			} else {
				mUsbmanager.requestPermission(mDevice, mPendingIntent);
			}
		} else {
			return;
		}
	}

	@SuppressLint("NewApi")
	public synchronized void CloseDevice() {
		try {
			Thread.sleep(10);
		} catch (Exception e) {
		}
		if (this.mDeviceConnection != null) {
			if (this.mInterface != null) {
				this.mDeviceConnection.releaseInterface(this.mInterface);
				this.mInterface = null;
			}

			this.mDeviceConnection.close();
		}

		if (this.mUsbDevice != null) {
			this.mUsbDevice = null;
		}

		if (this.mUsbmanager != null) {
			this.mUsbmanager = null;
		}
		isStop = true;
		/*
		 * No need unregisterReceiver
		 */
		this.mContext.unregisterReceiver(mUsbReceiver);
	}

	public boolean UsbFeatureSupported() {
		boolean bool = this.mContext.getPackageManager().hasSystemFeature(
				"android.hardware.usb.host");
		return bool;
	}

	public read_thread readThread;
	public boolean isStop = false;

	public void onStop(boolean isStop) {
		isStop = isStop;
	}

	// 读取数据的线程
	private class read_thread extends Thread {
		UsbEndpoint endpoint;
		UsbDeviceConnection mConn;
		String data = "";

		read_thread(UsbEndpoint point, UsbDeviceConnection con) {
			endpoint = point;
			mConn = con;
			this.setPriority(Thread.MAX_PRIORITY);

		}

		@SuppressLint("NewApi")
		public void run() {
			while (!isStop) {
				if (endpoint != null) {
					byte[] buffer = new byte[256];
					int readcount;
					readcount = mConn.bulkTransfer(endpoint, buffer, 64, 10000);
					if (readcount > 2) {

						byte[] contend = new byte[readcount];// 只传递有效数据内容
						for (int i = 0; i < readcount; i++) {

							contend[i] = buffer[i];
						}
						data = StringUtils.ByteArrToHex(contend);
						data = data.replace("31 60", "").trim();
						if (!data.equals("")) {
							if (data.indexOf("EE 35", 5) != -1) {
								data = "";
							} else {
								// System.out
								// .println("==========打印处获取到的数据========="
								// + data);
								handler.obtainMessage(
										JianHuYiActivity.READER_DATA,
										readcount, 1, data).sendToTarget();// 传递给界面更新数据
//								isGetData = true;
								data = "";
							}

						}
					} else
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					/*
					 * byte[] buf = new byte[64]; int count =
					 * mConn.bulkTransfer(endpoint, buf, 64, 10000); try { count
					 * = -1; } catch (Exception e) { System.out.println("打印异常" +
					 * e); isStop = true; }
					 */

				}
			}
		}
	}

	/***********
	 * USB broadcast receiver 接收廣播打開設備的權限
	 *******************************************/
	private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
				return;
			if (APPName.equals(action)) {
				// synchronized (this) {
				// UsbDevice localUsbDevice = (UsbDevice)
				// intent.getParcelableExtra("device");
				// if
				// (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,
				// false)) {
				// OpenDevice(localUsbDevice);
				// } else {
				// Toast.makeText(BeneCheckDevice.this.mContext,
				// "Deny USB Permission", Toast.LENGTH_SHORT).show();
				// }
				// }
			} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
				handler.obtainMessage(JianHuYiActivity.DISCONNT, "设备已断开")
						.sendToTarget();
				isStop = true;
				// 设备断开，把设备对象关掉，应该把读取数据的线程销毁。
				CloseDevice();

			} else {
				Log.d(TAG, "......");
			}
		}
	};

	public boolean isConnected() {
		return (this.mUsbDevice != null) && (this.mInterface != null)
				&& (this.mDeviceConnection != null);
	}

	public boolean SetConfig(int baudRate, byte dataBit, byte stopBit,
			byte parity, byte flowControl) {
		int value = 0;
		int index = 0;
		char valueHigh = 0, valueLow = 0, indexHigh = 0, indexLow = 0;
		switch (parity) {
		case 0: /* NONE */
			valueHigh = 0x00;
			break;
		case 1: /* ODD */
			valueHigh |= 0x08;
			break;
		case 2: /* Even */
			valueHigh |= 0x18;
			break;
		case 3: /* Mark */
			valueHigh |= 0x28;
			break;
		case 4: /* Space */
			valueHigh |= 0x38;
			break;
		default: /* None */
			valueHigh = 0x00;
			break;
		}

		if (stopBit == 2) {
			valueHigh |= 0x04;
		}

		switch (dataBit) {
		case 5:
			valueHigh |= 0x00;
			break;
		case 6:
			valueHigh |= 0x01;
			break;
		case 7:
			valueHigh |= 0x02;
			break;
		case 8:
			valueHigh |= 0x03;
			break;
		default:
			valueHigh |= 0x03;
			break;
		}

		valueHigh |= 0xc0;
		valueLow = 0x9c;

		value |= valueLow;
		value |= (int) (valueHigh << 8);

		switch (baudRate) {
		case 50:
			indexLow = 0;
			indexHigh = 0x16;
			break;
		case 75:
			indexLow = 0;
			indexHigh = 0x64;
			break;
		case 110:
			indexLow = 0;
			indexHigh = 0x96;
			break;
		case 135:
			indexLow = 0;
			indexHigh = 0xa9;
			break;
		case 150:
			indexLow = 0;
			indexHigh = 0xb2;
			break;
		case 300:
			indexLow = 0;
			indexHigh = 0xd9;
			break;
		case 600:
			indexLow = 1;
			indexHigh = 0x64;
			break;
		case 1200:
			indexLow = 1;
			indexHigh = 0xb2;
			break;
		case 1800:
			indexLow = 1;
			indexHigh = 0xcc;
			break;
		case 2400:
			indexLow = 1;
			indexHigh = 0xd9;
			break;
		case 4800:
			indexLow = 2;
			indexHigh = 0x64;
			break;
		case 9600:
			indexLow = 2;
			indexHigh = 0xb2;
			break;
		case 19200:
			indexLow = 2;
			indexHigh = 0xd9;
			break;
		case 38400:
			indexLow = 3;
			indexHigh = 0x64;
			break;
		case 57600:
			indexLow = 3;
			indexHigh = 0x98;
			break;
		case 115200:
			indexLow = 3;
			indexHigh = 0xcc;
			break;
		case 230400:
			indexLow = 3;
			indexHigh = 0xe6;
			break;
		case 460800:
			indexLow = 3;
			indexHigh = 0xf3;
			break;
		case 500000:
			indexLow = 3;
			indexHigh = 0xf4;
			break;
		case 921600:
			indexLow = 7;
			indexHigh = 0xf3;
			break;
		case 1000000:
			indexLow = 3;
			indexHigh = 0xfa;
			break;
		case 2000000:
			indexLow = 3;
			indexHigh = 0xfd;
			break;
		case 3000000:
			indexLow = 3;
			indexHigh = 0xfe;
			break;
		default: // default baudRate "9600"
			indexLow = 2;
			indexHigh = 0xb2;
			break;
		}

		index |= 0x88 | indexLow;
		index |= (int) (indexHigh << 8);

		Uart_Control_Out(UartCmd.VENDOR_SERIAL_INIT, value, index);
		if (flowControl == 1) {
			Uart_Tiocmset(UartModem.TIOCM_DTR | UartModem.TIOCM_RTS, 0x00);
		}
		return true;
	}

	@SuppressLint("NewApi")
	public int Uart_Control_Out(int request, int value, int index) {
		int retval = 0;
		if (mDeviceConnection != null) {
			retval = mDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR
					| UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_OUT, request,
					value, index, null, 0, DEFAULT_TIMEOUT);
		}
		return retval;
	}

	@SuppressLint("NewApi")
	public int Uart_Control_In(int request, int value, int index,
			byte[] buffer, int length) {
		int retval = 0;
		if (mDeviceConnection != null) {
			retval = mDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR
					| UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_IN, request,
					value, index, buffer, length, DEFAULT_TIMEOUT);
		}
		return retval;
	}

	private int Uart_Set_Handshake(int control) {
		return Uart_Control_Out(UartCmd.VENDOR_MODEM_OUT, ~control, 0);
	}

	public int Uart_Tiocmset(int set, int clear) {
		int control = 0;
		if ((set & UartModem.TIOCM_RTS) == UartModem.TIOCM_RTS)
			control |= UartIoBits.UART_BIT_RTS;
		if ((set & UartModem.TIOCM_DTR) == UartModem.TIOCM_DTR)
			control |= UartIoBits.UART_BIT_DTR;
		if ((clear & UartModem.TIOCM_RTS) == UartModem.TIOCM_RTS)
			control &= ~UartIoBits.UART_BIT_RTS;
		if ((clear & UartModem.TIOCM_DTR) == UartModem.TIOCM_DTR)
			control &= ~UartIoBits.UART_BIT_DTR;

		return Uart_Set_Handshake(control);
	}

	public boolean UartInit() {
		int ret;
		int size = 8;
		byte[] buffer = new byte[size];
		Uart_Control_Out(UartCmd.VENDOR_SERIAL_INIT, 0x0000, 0x0000);
		ret = Uart_Control_In(UartCmd.VENDOR_VERSION, 0x0000, 0x0000, buffer, 2);
		if (ret < 0)
			return false;
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x1312, 0xD982);
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x0f2c, 0x0004);
		ret = Uart_Control_In(UartCmd.VENDOR_READ, 0x2518, 0x0000, buffer, 2);
		if (ret < 0)
			return false;
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x2727, 0x0000);
		Uart_Control_Out(UartCmd.VENDOR_MODEM_OUT, 0x00ff, 0x0000);
		return true;
	}

	public final class UartModem {
		public static final int TIOCM_LE = 0x001;
		public static final int TIOCM_DTR = 0x002;
		public static final int TIOCM_RTS = 0x004;
		public static final int TIOCM_ST = 0x008;
		public static final int TIOCM_SR = 0x010;
		public static final int TIOCM_CTS = 0x020;
		public static final int TIOCM_CAR = 0x040;
		public static final int TIOCM_RNG = 0x080;
		public static final int TIOCM_DSR = 0x100;
		public static final int TIOCM_CD = TIOCM_CAR;
		public static final int TIOCM_RI = TIOCM_RNG;
		public static final int TIOCM_OUT1 = 0x2000;
		public static final int TIOCM_OUT2 = 0x4000;
		public static final int TIOCM_LOOP = 0x8000;
	}

	public final class UsbType {
		public static final int USB_TYPE_VENDOR = (0x02 << 5);
		public static final int USB_RECIP_DEVICE = 0x00;
		public static final int USB_DIR_OUT = 0x00; /* to device */
		public static final int USB_DIR_IN = 0x80; /* to host */
	}

	public final class UartCmd {
		public static final int VENDOR_WRITE_TYPE = 0x40;
		public static final int VENDOR_READ_TYPE = 0xC0;
		public static final int VENDOR_READ = 0x95;
		public static final int VENDOR_WRITE = 0x9A;
		public static final int VENDOR_SERIAL_INIT = 0xA1;
		public static final int VENDOR_MODEM_OUT = 0xA4;
		public static final int VENDOR_VERSION = 0x5F;
	}

	public final class UartState {
		public static final int UART_STATE = 0x00;
		public static final int UART_OVERRUN_ERROR = 0x01;
		public static final int UART_PARITY_ERROR = 0x02;
		public static final int UART_FRAME_ERROR = 0x06;
		public static final int UART_RECV_ERROR = 0x02;
		public static final int UART_STATE_TRANSIENT_MASK = 0x07;
	}

	public final class UartIoBits {
		public static final int UART_BIT_RTS = (1 << 6);
		public static final int UART_BIT_DTR = (1 << 5);
	}

	/*
	 * public int WriteData(byte[] buf, int length) throws IOException { int
	 * mLen = 0; mLen = WriteData(buf, length, 10000); if (mLen < 0) { throw new
	 * IOException("Expected Write Actual Bytes"); } return mLen; }
	 */
	// 是否已经获取到数据，用来设置10秒钟后超时的标记
//	boolean isGetData = false;
//	Handler mGetDataHandler = new Handler();
//	Runnable mGetDataRunnable = new Runnable() {
//		@Override
//		public void run() {
//			if (!isGetData) {
//				handler.obtainMessage(WHAT_RECEIVE_TIMEOUT).sendToTarget();
//			}
//		}
//	};
	@SuppressLint("NewApi")
	public int WriteData(byte[] buf, int length, int timeoutMillis) {
//		isGetData = false;
		// 10秒后执行mGetDataRunnable任务，检查是否获取数据
//		mGetDataHandler.postDelayed(mGetDataRunnable, 10000L);
		int offset = 0;
		int HasWritten = 0;
		int odd_len = length;
		if (this.mBulkOutPoint == null) {
			// System.out.println("结束");
			return -1;
		}
		while (offset < length) {
			synchronized (this.WriteQueueLock) {
				int mLen = Math.min(odd_len, this.mBulkPacketSize);
				byte[] arrayOfByte = new byte[mLen];
				if (offset == 0) {
					System.arraycopy(buf, 0, arrayOfByte, 0, mLen);
				} else {
					System.arraycopy(buf, offset, arrayOfByte, 0, mLen);
				}
				HasWritten = this.mDeviceConnection.bulkTransfer(
						this.mBulkOutPoint, arrayOfByte, mLen, timeoutMillis);
				// System.out.println("发送的数据" + Arrays.toString(arrayOfByte));
				if (HasWritten < 0) {
					return -2;
				} else {
					offset += HasWritten;
					odd_len -= HasWritten;
				}
			}
		}
		// System.out.println("发送成功" + offset);
		return offset;
	}

	public void close() {
		isStop = true;
		mContext.unregisterReceiver(mUsbReceiver);

	}
}
